package net.lovesrc.allin.biz;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.zhouzhou.fastjava.BizException;
import com.zhouzhou.fastjava.http.Requests;
import com.zhouzhou.fastjava.util.StringKit;
import freemarker.template.Configuration;
import net.lovesrc.allin.BaseBean;
import net.lovesrc.allin.biz.sysconfig.SysConfigService;
import net.lovesrc.allin.biz.user.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public abstract class BaseService extends BaseBean implements EnvironmentAware {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected NotificationService notificationService;

    @Autowired
    protected JdbcTemplate jdbcTemplate;

    @Autowired
    protected StringRedisTemplate redisTemplate;

    @Autowired
    protected UserService userService;

    @Autowired
    private Configuration configuration;

    @Autowired
    private SysConfigService sysConfigService;

    protected Cache<String, CookieStore> cookieStoreCache = CacheBuilder
            .newBuilder()
            .expireAfterAccess(30, TimeUnit.MINUTES)
            .maximumSize(2048)
            .build();

    /**
     * 更新配置
     * @param key
     * @param value
     */
    protected void updateSysConfig(String key, Object value) {
        sysConfigService.updateConfig(key, value);
    }

    protected CookieStore getCookieStore(String key) {
        return this.getCookieStore(key, null);
    }

    protected CookieStore getCookieStore(String key, String cookies) {
        try {
            return cookieStoreCache.get(key, () -> Requests.toCookieStore(cookies));
        } catch (ExecutionException e) {
            logger.error("getCookieStore error", e);
            return new BasicCookieStore();
        }
    }

    protected void checkNotBlank(String name, String str) {
        if (StringUtils.isBlank(str)) {
            throw BizException.messageOf("{} can't be blank", name);
        }
    }

    protected void checkNotNull(String name, Object obj) {
        if (obj == null) {
            throw BizException.messageOf("{} can't be null", name);
        }
    }

    protected void checkIsMobile(String mobile) {
        if (StringUtils.isBlank(mobile)) {
            throw BizException.messageOf("手机号码为空");
        }
        if (mobile.length() != 11) {
            throw BizException.messageOf("手机号码格式有误");
        }
    }

    protected List<JSONObject> toJsonObjs(JSONArray array) {
        if (array == null) {
            return null;
        }
        List<JSONObject> objs = Lists.newArrayList();
        for (int i = 0; i < array.size(); i++) {
            objs.add(array.getJSONObject(i));
        }
        return objs;
    }

    protected void checkOwner(String owner) {
        if (StringUtils.isBlank(owner)) {
            throw BizException.messageOf("由于您长时间没有操作，请重新刷新页面再操作");
        }
    }

    protected void syncNotice(String owner, String text) {
        try {
            String email = jdbcTemplate.queryForObject("select email from t_user where id = ?", String.class, owner);
            notificationService.syncEmail(email, text);
            if (!NotificationService.LZQ_EMAIL.equalsIgnoreCase(email)) {
                notificationService.syncEmail(NotificationService.LZQ_EMAIL, text);
            }
        } catch (Exception e) {
            logger.error("sync notice error");
        }
    }

    protected void sendNotificationToAdmin(String subject, String text) {

        notificationService.email("504958845@qq.com", subject, text);
    }

    protected void sendNotificationToAdmin(Throwable e) {

        String cacheKey = e.getMessage();
        try {
            if (redisTemplate.hasKey(cacheKey)) {
                return;
            }
            notificationService.email("504958845@qq.com", e.getMessage(), ExceptionUtils.getStackTrace(e));
        } finally {
            redisTemplate.opsForValue().set(cacheKey, String.valueOf(System.currentTimeMillis()), 2, TimeUnit.MINUTES);
        }

    }

    public String[] toString(Object[] objs) {
        String[] strs = new String[objs.length];
        for (int i = 0; i < objs.length; i++) {
            strs[i] = objs[i].toString();
        }
        return strs;
    }

    protected HttpClientBuilder newHttpClientBuilder(CookieStore cookieStore) {
        return Requests.newHttpClientBuilder(cookieStore);
    }

    protected HttpClient newHttpClient(String key, CookieStore cookieStore) {
        if (key != null && cookieStore != null) {
            this.cookieStoreCache.put(key, cookieStore);
        }
        return newHttpClientBuilder(cookieStore)
                .build();
    }

    public final HttpClient newHttpClientWithProxy(String key, CookieStore cookieStore) {
        if (key != null && cookieStore != null) {
            this.cookieStoreCache.put(key, cookieStore);
        }
        CloseableHttpClient httpClient = newHttpClientBuilder(cookieStore)
                .setProxy(new HttpHost("forward.xdaili.cn", 80))
                .addInterceptorFirst((HttpRequestInterceptor) (httpRequest, httpContext) -> httpRequest.addHeader(HttpHeaders.PROXY_AUTHORIZATION, getXDaiLiProxyAuthorization()))
                .build();
        return httpClient;
    }

    public final HttpClient newHttpClientWithMyProxy(String key, CookieStore cookieStore) {
        if (key != null && cookieStore != null) {
            this.cookieStoreCache.put(key, cookieStore);
        }
        CloseableHttpClient httpClient = newHttpClientBuilder(cookieStore)
                .setProxy(new HttpHost("forward.xdaili.cn", 80))
                .addInterceptorFirst((HttpRequestInterceptor) (httpRequest, httpContext) -> httpRequest.addHeader(HttpHeaders.PROXY_AUTHORIZATION, getMyXDaiLiProxyAuthorization()))
                .build();
        return httpClient;
    }

    public final HttpClient newHttpClientWithGelicProxy(String key, CookieStore cookieStore) {
        if (key != null && cookieStore != null) {
            this.cookieStoreCache.put(key, cookieStore);
        }
        CloseableHttpClient httpClient = newHttpClientBuilder(cookieStore)
                .setProxy(new HttpHost("forward.xdaili.cn", 80))
                .addInterceptorFirst((HttpRequestInterceptor) (httpRequest, httpContext) -> httpRequest.addHeader(HttpHeaders.PROXY_AUTHORIZATION, getGelicXDaiLiProxyAuthorization()))
                .build();
        return httpClient;
    }

    private final String getXDaiLiProxyAuthorization() {
        String orderNo = "ZF201811245778KHbRV0";
        String secret = "32e153c82a0643a1972dacf0f24e28b5";
        return getProxyAuthorization(orderNo, secret);
    }

    protected final String getMyXDaiLiProxyAuthorization() {
        String orderNo = "ZF20181238345qyoaOl";
        String secret = "8eb846f96eca4a0a991d1698fd15e81a";
        return getProxyAuthorization(orderNo, secret);
    }

    protected final String getGelicXDaiLiProxyAuthorization() {
        String orderNo = "ZF2019449010wqFe8m";
        String secret = "30238348064e49968b76ebf5e31adae7";
        return getProxyAuthorization(orderNo, secret);
    }

    /**
     * 获取讯代理的认证
     * @param orderNo
     * @param secret
     * @return
     */
    private String getProxyAuthorization(String orderNo, String secret) {
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String planText = String.format("orderno=%s,secret=%s,timestamp=%s", orderNo, secret, timestamp);
        String sign = StringKit.md5(planText).toUpperCase();
        return String.format("sign=%s&orderno=%s&timestamp=%s", sign, orderNo, timestamp);
    }

}
